using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace NWT
{
	/// <summary>
	/// Contains functionality to control the state of the Bluetooth hardware on a Smart Device.
	/// </summary>
	/// <remarks>This class currently only supports devices which use the Microsoft Bluetooth stack such as the Orange SPV E200, devices which use the WidComm stack will not work.</remarks>
	public class Bluetooth : IDisposable
	{

		/// <summary>
		/// Pointer to widcomm stack
		/// </summary>
		protected static IntPtr WidcommStack = IntPtr.Zero;

		/// <summary>
		/// Ms bt status
		/// </summary>
		protected RadioMode MicrosoftBtMode = RadioMode.PowerOff;

		/// <summary>
		/// Inited flag
		/// </summary>
		protected bool Inited = false;
		
		/// <summary>
		/// Disable constructor
		/// </summary>
		public Bluetooth() { }

		/// <summary>
		/// Destructor
		/// </summary>
		~Bluetooth()
		{
			Dispose(false);
		}

		/// <summary>
		/// Init bluetooth
		/// </summary>
		public void Init()
		{
			// check ms stack
			if (BthGetMode(ref MicrosoftBtMode) == 0)
			{
				if (MicrosoftBtMode != RadioMode.PowerOff)
					BthSetMode(RadioMode.Discoverable);
				Inited = true;
				return;
			}
			// check widcomm stack
			else if (WidcommStackPresent() != 0)
			{
				WidcommStack = CreateStack();
				Inited = true;
				return;
			}
		}

		/// <summary>
		/// Disposed flag
		/// </summary>
		private bool m_bDisposed = false;

		/// <summary>
		/// Dispose object
		/// </summary>
		/// <param name="bDisposing"></param>
		protected void Dispose(bool bDisposing)
		{
			if (m_bDisposed)
				return;

			if (Inited)
			{
				if (WidcommStack != IntPtr.Zero)
				{
					DeleteStack(WidcommStack);
					WidcommStack = IntPtr.Zero;
				}
				else
				{
					if (MicrosoftBtMode == RadioMode.PowerOff)
						BthSetMode(MicrosoftBtMode);
				}
			}

			m_bDisposed = true;
		}

		/// <summary>
		/// Free resources
		/// </summary>
		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		/// <summary>
		/// MS bluetooth stack
		/// </summary>
		/// <param name="dwMode"></param>
		/// <returns></returns>
		[DllImport("BthUtil.dll")]
		private static extern int BthSetMode(RadioMode dwMode);

		/// <summary>
		/// MS bluetooth stack
		/// </summary>
		/// <param name="dwMode"></param>
		/// <returns></returns>
		[DllImport("BthUtil.dll")]
		private static extern int BthGetMode(ref RadioMode dwMode);

		/// <summary>
		/// Widcomm bluetooth stack
		/// </summary>
		/// <returns></returns>
		[DllImport("wc_bluetooth.dll", SetLastError = false, CharSet = CharSet.Unicode)]
		internal static extern int WidcommStackPresent();

		/// <summary>
		/// Widcomm bluetooth stack
		/// </summary>
		/// <returns></returns>
		[DllImport("wc_bluetooth.dll", SetLastError = false, CharSet = CharSet.Unicode)]
		internal static extern IntPtr CreateStack();

		/// <summary>
		/// Widcomm bluetooth stack
		/// </summary>
		/// <returns></returns>
		[DllImport("wc_bluetooth.dll", SetLastError = false, CharSet = CharSet.Unicode)]
		internal static extern void DeleteStack(IntPtr pStack);
	}

	/// <summary>
	/// Determine all the possible modes of operation of the Bluetooth radio.
	/// </summary>
	public enum RadioMode
	{
		/// <summary>
		/// Bluetooth is disabled on the device.
		/// </summary>
		PowerOff,
		/// <summary>
		/// Bluetooth is connectable but your device cannot be discovered by other devices.
		/// </summary>
		Connectable,
		/// <summary>
		/// Bluetooth is activated and fully discoverable.
		/// </summary>
		Discoverable,
	}
}
